﻿using MicroMVVM.Services.Interfaces;
using System;
using System.Net.NetworkInformation;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using Windows.Networking.Connectivity;

namespace MicroMVVM.Services.Implementation.Any
{
    /// <summary>
    /// This class represents the service to check the internet connection.
    /// </summary>
    [ExportService(ServiceType.Any, typeof(IConnectionService), PartCreationPolicy.Singleton)]
    public class ConnectionService : IConnectionService
    {
        private Subject<bool> _status;
        private bool _isConnected;

        /// <summary>
        /// This property checks whether there an internet connection is available.
        /// </summary>
        /// <returns>True/False</returns>
        public bool IsConnected
        {
            get
            {
                var connectionProfile = NetworkInformation.GetInternetConnectionProfile();

                return (NetworkInterface.GetIsNetworkAvailable() &&
                        connectionProfile != null &&
                        connectionProfile.GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess);
            }
        }

        /// <summary>
        /// On listening to this property, the application will be notified if an internet connection is lost or becomes available.
        /// </summary>
        public IObservable<bool> Status
        {
            get { return _status = _status ?? Initialise(); }
        }

        /// <summary>
        /// This method initialises the class.
        /// </summary>
        private Subject<bool> Initialise()
        {
            var subject = new Subject<bool>();

            Observable.Interval(TimeSpan.FromSeconds(3)).ObserveOnDispatcher().Subscribe(
                status =>
                {
                    var isConnected = IsConnected;

                    if (_isConnected == isConnected) return;

                    _isConnected = isConnected;

                    subject.OnNext(_isConnected);
                },
                subject.OnError,
                subject.OnCompleted);

            return subject;
        }
    }
}